package com.rain.controller;

import com.rain.enums.ResponseCodeEnum;

import com.rain.query.ResponseVO;

import com.rain.exception.BusinessException;

import lombok.extern.slf4j.Slf4j;;

import org.springframework.beans.TypeMismatchException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 全局异常处理器
 * <p>
 * 统一处理所有 Controller 中抛出的异常，返回标准 JSON 响应
 *
 * @author Rain
 */
@RestControllerAdvice
@Slf4j
public class AGlobalExceptionHandlerController extends BaseController {

    /**
     * 处理所有未捕获的异常（默认兜底）
     */
    @ExceptionHandler(Exception.class)
    public ResponseVO<?> handleException(Exception e, HttpServletRequest request) {
        log.error("请求错误，请求地址：{}，错误信息：", request.getRequestURL(), e);
        return getErrorResponseVO(ResponseCodeEnum.CODE_500);
    }

    /**
     * 处理 404 错误（请求地址不存在）
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseVO<?> handleNotFound(NoHandlerFoundException e, HttpServletRequest request) {
        log.warn("请求地址不存在：{}", request.getRequestURL());
        return getErrorResponseVO(ResponseCodeEnum.CODE_404);
    }

    /**
     * 处理 405 错误（请求方法不支持）
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseVO<?> handleMethodNotAllowed(HttpRequestMethodNotSupportedException e) {
        log.warn("请求方法不支持：{}", e.getMethod());
        return getErrorResponseVO(ResponseCodeEnum.CODE_405);
    }

    /**
     * 处理业务异常（自定义 BusinessException）
     */
    @ExceptionHandler(BusinessException.class)
    public ResponseVO<?> handleBusinessException(BusinessException e) {
        log.warn("业务异常：{}", e.getMessage());
        return getErrorResponseVO(e.getCodeEnum() != null ? e.getCodeEnum() : ResponseCodeEnum.CODE_500);
    }

    /**
     * 处理参数绑定异常（如 JSON 解析失败）
     */
    @ExceptionHandler(BindException.class)
    public ResponseVO<?> handleBindException(BindException e) {
        log.warn("参数绑定异常：{}", e.getMessage());
        return getErrorResponseVO(ResponseCodeEnum.CODE_600);
    }

    /**
     * 处理参数类型错误（如 String 转 Integer 失败）
     */
    @ExceptionHandler(TypeMismatchException.class)
    public ResponseVO<?> handleTypeMismatchException(TypeMismatchException e) {
        log.warn("参数类型错误：{}", e.getMessage());
        return getErrorResponseVO(ResponseCodeEnum.CODE_600);
    }

    /**
     * 处理主键冲突（DuplicateKeyException）
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public ResponseVO<?> handleDuplicateKeyException(DuplicateKeyException e) {
        log.warn("主键冲突：{}", e.getMessage());
        return getErrorResponseVO(ResponseCodeEnum.CODE_601);
    }

    /**
     * 处理空指针异常（建议在业务层避免）
     */
    @ExceptionHandler(NullPointerException.class)
    public ResponseVO<?> handleNullPointerException(NullPointerException e) {
        log.error("空指针异常：{}", e.getMessage());
        return getErrorResponseVO(ResponseCodeEnum.CODE_500);
    }
}
